package com.moon.game.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.log4j.Logger;

import com.moon.game.constants.Constants;
import com.moon.game.exception.GException;
import com.moon.game.manager.ItemMG;
import com.moon.game.resource.model.Item;
import com.moon.game.resource.model.Monster;
import com.moon.game.util.GDateUtils;
import com.moon.game.vos.FightResult;
import com.moon.game.vos.PlayerVo;
import com.moon.game.vos.PlayerVo.UsedItem;

/**
 * @description 战斗服务
 * @author Ranger 作者 E-mail:haozi000005@163.com
 * @version 创建时间：2012-5-11 上午9:57:30
 */
public class FightService {
	private static final Logger log = Logger.getLogger(FightService.class);
	
	/**
	 * 寻怪
	 * 
	 * @param player
	 * @param mainlandId 大陆id
	 * @return 返回怪物id列表
	 */
	public static ArrayList<Monster> findMonster(PlayerVo player) {
		MainLandService landService = MainLandService.getMainLandService(player.getLocation());
		ConcurrentHashMap<String, Monster> res = landService.getMonsters();
		ArrayList<Monster> monsterList = new ArrayList<Monster>();
		Random random = new Random();
		if (res != null && res.size() > 0) {
			//随机怪物的个数，一次寻怪最多出现三个怪物，最少一个
			int sum = random.nextInt(3) + 1;
			int loopTimes = 1; 
			for (Map.Entry<String, Monster> entry : res.entrySet()) {
				Monster monster = entry.getValue();
				loopTimes ++;
				if (loopTimes % 50 != 0) {
					//连续50次选到的怪物都是超过等级很多的强制加载下次出现的怪物
					if (player.getLevel() + 10 < monster.getLevel() && random.nextInt(1000) + 1 >= 1) {
						//超过玩家等级10级的怪物0.1%的可能会被选中
						continue;
					}
					if (player.getLevel() + 5 < monster.getLevel() && random.nextInt(1000) + 1 >= 3) {
						//超过玩家等级5级的怪物0.3%的可能会被选中
						continue;
					}
				}
				//是可以被打的boss只取出一只
				if (monster.getReviveTime() > 0 && monster.getDeadTime() == 0 && monster.getFighter() == null) {
					monsterList.add(monster);
					break;
				}
				//重新寻怪，将原来的怪物还回内存
				if (player.getId().equals(monster.getFighter())) {
					monster.setFighter(null);
					continue;
				}
				//不是boss取出sum只
				if (monster.getFighter() == null) {
					monsterList.add(monster);
					monster.setFighter(player.getId());
					if (--sum <= 0) {
						break;
					}
				}
			}
		}
		return monsterList;
	}
	
	/**
	 * 和指定怪物战斗
	 * 
	 * @param id
	 * 
	 * @return 战斗结果状态;0战斗成功,1怪物已经被别人抢走,2您的位置参数错误,3怪物已经不存在
	 */
	public static FightResult doFightMonster(PlayerVo player,String id) {
		Monster monster = null;
		FightResult result = new FightResult();
		try {
			monster = doFindMonsterById(player.getLocation(), id);
		} catch (GException e) {
			log.warn("this people [" + player.getId() + "]has err location" + player.getLocation());
			e.printStackTrace();
			result.setStatus(Constants.FIGHT_ERR_LOCATION);
			return result;
		}
		if (monster == null) {
			log.warn("this people [" + player.getId() + "]find the monster is null!");
			result.setStatus(Constants.FIGHT_NO_MONSTER);
			return result;
		}else {
			if (monster.getFighter() != null && !monster.getFighter().equals(player.getId())) {
				result.setStatus(Constants.FIGHT_MONSTER_SNATCHED);
				return result;
			}
			//战斗过程计算
			//人物属性
			FighterEntity srcFighter = new FighterEntity();
			//计算player战斗属性
			calculatPlayerValue(player, srcFighter);
			
			//怪物属性
			FighterEntity dstFighter = new FighterEntity();
			calculatMonsterValue(monster, dstFighter);
			
			//最终计算出来人物属性
			int srcHotAtt = fightRandomValue(srcFighter.getHotMinAttc(),srcFighter.getHotMaxAttc());
			int srcColdAtt = fightRandomValue(srcFighter.getColdMinAttc(),srcFighter.getColdMaxAttc());
			int srcHotDec = fightRandomValue(srcFighter.getHotMinDec(),srcFighter.getHotMaxDec());
			int srcColdDec = fightRandomValue(srcFighter.getColdMinDec(),srcFighter.getColdMaxDec());
			
			//最终计算出来怪物属性
			int dstHotAtt = fightRandomValue(dstFighter.getHotMinAttc(),dstFighter.getHotMaxAttc());
			int dstColdAtt = fightRandomValue(dstFighter.getColdMinAttc(),dstFighter.getColdMaxAttc());
			int dstHotDec = fightRandomValue(dstFighter.getHotMinDec(),dstFighter.getHotMaxDec());
			int dstColdDec = fightRandomValue(dstFighter.getColdMinDec(),dstFighter.getColdMaxDec());
			
			int srcHurt = 0;
			int dstHurt = 0;
			srcHurt = (dstColdAtt - srcColdDec) > 0 ? (dstColdAtt - srcColdDec) : 0 + (dstHotAtt - srcHotDec) > 0 ? (dstHotAtt - srcHotDec) : 0;
			dstHurt = (srcColdAtt - dstColdDec) > 0 ? (srcColdAtt - dstColdDec) : 0 + (srcHotAtt - dstHotDec) > 0 ? (srcHotAtt - dstHotDec) : 0;
			
			//计算怪物当前气血
			int monsterCurHp = monster.getCurHp() - dstHurt > 0 ? (monster.getCurHp() - dstHurt) : 0;
			monster.setCurHp(monsterCurHp);
			
			//计算人物当前气血并重置人物当前HP(只有怪物没有死亡的情况下才计算人物当前血量)
			if (monsterCurHp > 0) {
				PlayerService.doAddHp(player.getSid(), player.getId(), -srcHurt);
//				UpdatePlayerThread.addSyncPlayerMap(player);
				PlayerService.doUpdatePlayer(player.getSid(), player.getId(), player);
			}else {
				//怪物死亡
				result.setMoney(monster.getMoney());
				HashMap<Integer, Integer> dropItems = dropItem(monster.getDropItemProb());
				for (Map.Entry<Integer, Integer> entry : dropItems.entrySet()) {
					result.addItem(entry.getKey(), entry.getValue());
				}
			}
			
			result.setSrcHp(player.getHp());
			result.setSrcCurHp(player.getCurHp());
			result.setSrcHurtHp(srcHurt);
			result.setDstHp(monster.getHp());
			result.setDstCurHp(monster.getCurHp());
			result.setDstHurtHp(dstHurt);
			
			//设置怪物正在被谁攻击以及攻击时间
			monster.setLastFightTime(GDateUtils.now());
			monster.setFighter(player.getId());
			
			return result;
		}
	}
	
	/**
	 * 物品掉落(任何怪物只可能掉落一件装备道具)
	 * 
	 * @param values 格式id:num
	 * @return
	 */
	private static HashMap<Integer, Integer> dropItem(String values) {
		HashMap<Integer, Integer> idNum = new HashMap<Integer, Integer>();
		if (!"".equals(values)) {
			String[] cells = values.split("[|]");
			boolean hasDropedPlayerItem = false;
			for (String  cell: cells) {
				String[] idAndNum = cell.split("[:]");
				Integer id = Integer.parseInt(idAndNum[0]);
				if (!hasDropedPlayerItem) {
					idNum.put(id, Integer.parseInt(idAndNum[1]));
				}
				Item item = ItemMG.instance.getItem(id);
				if (item == null) {
					log.error("there is drop a ET, id is[" + id + "]!");
					continue;
				}
				if (item.getPosition() > 0) {
					hasDropedPlayerItem = true;
				}
			}
		}
		return idNum;
	}
	
	/**
	 * 计算人物所有属性
	 * 
	 */
	private static void calculatPlayerValue(PlayerVo player, FighterEntity fighter) {
		addEquipsValue(player, fighter);
		addSelfValue(player, fighter);
	}
	
	/**
	 * 计算怪物所有属性
	 * 
	 * @param monster
	 * @param fighter
	 */
	private static void calculatMonsterValue(Monster monster, FighterEntity fighter) {
		addMonsterValue(monster, fighter);
	}
	
	/**
	 * 增加怪物本身属性
	 * 
	 * @param monster
	 * @param fighter
	 */
	private static void addMonsterValue(Monster monster, FighterEntity fighter) {
		if (monster.getAttackHotMin() > 0) {
			fighter.setHotMinAttc(fighter.getHotMinAttc() + monster.getAttackHotMin());
		}
		if (monster.getAttackHotMax() > 0) {
			fighter.setHotMaxAttc(fighter.getHotMaxAttc() + monster.getAttackHotMax());
		}
		if (monster.getAttackColdMin() > 0) {
			fighter.setColdMinAttc(fighter.getColdMinAttc() + monster.getAttackColdMin());
		}
		if (monster.getAttackColdMax() > 0) {
			fighter.setColdMaxAttc(fighter.getColdMaxAttc() + monster.getAttackColdMax());
		}
		if (monster.getDefenseHotMin() > 0) {
			fighter.setHotMinDec(fighter.getHotMinDec() + monster.getDefenseHotMin());
		}
		if (monster.getDefenseHotMax() > 0) {
			fighter.setHotMaxDec(fighter.getHotMaxDec() + monster.getDefenseHotMax());
		}
		if (monster.getDefenseColdMin() > 0) {
			fighter.setColdMinDec(fighter.getColdMinDec() + monster.getDefenseColdMin());
		}
		if (monster.getDefenseColdMax() > 0) {
			fighter.setColdMaxDec(fighter.getColdMaxDec() + monster.getDefenseColdMax());
		}
	}
	
	
	/**
	 * 增加人物本身属性
	 * 
	 */
	private static void addSelfValue(PlayerVo player,FighterEntity fighter) {
		fighter.setHotMaxAttc(fighter.getHotMaxAttc() + player.getAttackHot());
		fighter.setColdMaxAttc(fighter.getColdMaxAttc() + player.getAttackCold());
		fighter.setHotMaxDec(fighter.getHotMaxDec() + player.getDefenseHot());
		fighter.setColdMaxDec(fighter.getColdMaxDec() + player.getDefenseCold());
	}
	
	/**
	 * 增加装备属性
	 * 
	 */
	private static void addEquipsValue(PlayerVo player,FighterEntity fighter) {
		//装备属性
		List<UsedItem> playerItems = player.getUsedItem(); 
		if (PlayerItemService.getPlayerItems(player.getId()) != null && playerItems != null) {
//			for (PlayerItem playerItem : PlayerItemService.getPlayerItems(player.getId())) {
			for (UsedItem playerItem : playerItems) {
//				if (!playerItem.getIsUse()) {
//					continue;
//				}
				if (playerItem.getAttackHotMin() > 0) {
					fighter.setHotMinAttc(fighter.getHotMinAttc() + playerItem.getAttackHotMin());
				}
				if (playerItem.getAttackHotMax() > 0) {
					fighter.setHotMaxAttc(fighter.getHotMaxAttc() + playerItem.getAttackHotMax());
				}
				if (playerItem.getAttackColdMin() > 0) {
					fighter.setColdMinAttc(fighter.getColdMinAttc() + playerItem.getAttackColdMin());
				}
				if (playerItem.getAttackColdMax() > 0) {
					fighter.setColdMaxAttc(fighter.getColdMaxAttc() + playerItem.getAttackColdMax());
				}
				if (playerItem.getDefenseHotMin() > 0) {
					fighter.setHotMinDec(fighter.getHotMinDec() + playerItem.getDefenseHotMin());
				}
				if (playerItem.getDefenseHotMax() > 0) {
					fighter.setHotMaxDec(fighter.getHotMaxDec() + playerItem.getDefenseHotMax());
				}
				if (playerItem.getDefenseColdMin() > 0) {
					fighter.setColdMinDec(fighter.getColdMinDec() + playerItem.getDefenseColdMin());
				}
				if (playerItem.getDefenseColdMax() > 0) {
					fighter.setColdMaxDec(fighter.getColdMaxDec() + playerItem.getDefenseColdMax());
				}
			}
		}
	}
	
	/**
	 * 战斗过程数值
	 * 
	 * @param min
	 * @param max
	 * @return
	 */
	private static int fightRandomValue(int min, int max) { 
		if (max <= min) {
			return min;
		}
		return new Random().nextInt(max - min) + 1 + min;
	}
	
	/**
	 * 查找指定大陆的怪物资源
	 * 
	 * @param landId
	 * @param id
	 * @return
	 * @throws GException
	 */
	private synchronized static ConcurrentHashMap<String, Monster> findMonsterRes(int landId,String id) throws GException {
		MainLandService landService = MainLandService.getMainLandService(landId);
		if (landService == null) {
			throw new GException("player location err" + landId);
		}
		ConcurrentHashMap<String, Monster> res = landService.getMonsters();
		return res;
	}
	
	/**
	 * 根据怪物id获取怪物对象
	 * 
	 * @param player
	 * @param id
	 * @return
	 * @throws GException 
	 */
	public synchronized static Monster doFindMonsterById(int landId,String id) throws GException {
		ConcurrentHashMap<String, Monster> res = findMonsterRes(landId, id);
		Monster monster = res.get(id);
		return monster;
	}
	
	/**
	 * 移除指定怪物(移除同时生成新的怪物添加到内存)
	 * 
	 * @param monsterId
	 * @throws GException 
	 */
	public synchronized static void removeTheMonster(int landId,String id) throws GException {
		ConcurrentHashMap<String, Monster> res = findMonsterRes(landId, id);
		Monster toRemoveMonster = res.remove(id);
		Monster newMonster = MainLandService.addMonsterToLand(toRemoveMonster.getId(), landId);
		res.put(newMonster.getMonsterId(), newMonster);
	}
	
}
